#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <TlHelp32.h>
#include <winsock.h>
#include <string.h>
#include <time.h>

#include "common.h"
#include "clientSide.h"

#pragma comment(lib, "Ws2_32.lib")

/*
 * this function get the FileContent request answer's header with data about the incomming file
 */
BOOL getFileRequestHeader(SOCKET sd,size_t* pFileSize)
{
	char ansBuffer[FILE_RES_HEADER_SIZE];
	if (recvTcpBuffer(sd,(char*)&ansBuffer,FILE_RES_HEADER_SIZE) != FILE_RES_HEADER_SIZE)
	{
		printf("Error: no answer from server\n");
		return FALSE;
	}

	//check that header is valid (protocol prefix and message id)
	if (!verifyIncommingFileHeader((char*)&ansBuffer,pFileSize))
	{
		printf("Error: invalid file header\n");
		return FALSE;
	}

	return TRUE;

}

/*
 * this function reads file content from the server's socket and save it to the disk
 */
BOOL saveFileContent(SOCKET sd,char* pFilePath,size_t fileSize)
{
	FILE* fd = NULL;
	char fileContent[FILE_BLOCK_SIZE];
	int readBytes;

	//create empty binary file
	fopen_s(&fd,pFilePath+findFileNameFromPath(pFilePath,strlen(pFilePath)),"wb");

	if (fd == NULL)
	{
		printf("Error: can't open a new file\n");
		return FALSE;
	}
	
	printf("Downloading %s\n",pFilePath+findFileNameFromPath(pFilePath,strlen(pFilePath)));

	while(fileSize > 0)
	{
		//calc the remaining bytes
		readBytes = min(FILE_BLOCK_SIZE,fileSize);

		//read them from the server's socket
		if (recvTcpBuffer(sd,fileContent,readBytes) != readBytes)
		{
			printf("Error: can't read file content from server\n");
			break;
		}

		//write this block to the disk
		if (fwrite(fileContent,sizeof(char),readBytes,fd) != (size_t)readBytes)
		{
			printf("Error: can't write file content\n");
			break;
		}

		//update total remaining size
		fileSize-=(unsigned short)readBytes;
	}

	if (fd != NULL)
	{
		fclose(fd);
	}

	//cehck if we got the whole file
	return fileSize == 0;
}

/*
 * this function gets a file from a server
 */
BOOL getFileFromServer(unsigned long serverIp,unsigned short serverTcpPort,char* filePath)
{
	SOCKET sd;								/* The socket descriptor */
	BOOL retValue = FALSE;

	unsigned short filePathLength = (unsigned short)strlen(filePath);
	
	size_t fileSize = 0;

	do
	{
		//connect to server
		sd = connectToServer(serverIp,serverTcpPort);
		if(sd == INVALID_SOCKET)
		{
			break;
		}

		//send file content request
	   if (!sendFileRequest(sd,filePath,filePathLength))
	   {
		   break;
	   }
		
	   //get file header
	   if (!getFileRequestHeader(sd,&fileSize))
	   {
		   break;
	   }
		
	   //get file content
	   if (!saveFileContent(sd,filePath,fileSize))
	   {
		   break;
	   }

	   retValue = TRUE;

#pragma warning(suppress:4127)
	}while(FALSE);
	   
	   
	if (sd != INVALID_SOCKET )
	{
	   closesocket(sd);
	}

	return retValue;;
}

int main(int argc, char* argv[])
{
	unsigned short port;
	unsigned long ip;
	int sid;
	WSADATA w;		
	
	if (argc != 3)
	{
		printf("Usage: %s <SID> <path to file on server>\n",argv[0]);
		exit(-1);
	}
	do
	{
		sid = atoi(argv[1]);
		

		if (sid == 0)
		{
			printf("Error while reading sid\n");
			break;
		}
	
		//open windows connections
		if (WSAStartup(0x0101, &w) != 0)
		{
			printf("Error: Could not open Windows connection.\n");
			break;
		}

		printf("Searching for server...");

		if (sendClientHelloMsg(sid,&ip,&port))
		{
			printf("Server found!\n");
		}
		else
		{
			printf("Server not found!\n");
			break;
		}
		
		if (getFileFromServer(ip,port,argv[2]))
		{
			printf("file been downloaded succesfully!\n");
		}
		else
		{
			printf("file not downloaded succesfully!\n");
		}
		
#pragma warning(suppress:4127) //enable single exit point
	}while(FALSE);

	WSACleanup();

	return 0;
}

